
#include "world.h"
#include "MiscFunctions.h"
#include "Terrain.h"
#include <ctime>
#include <math.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include < GL/glut.h >

using namespace std;

#define WINDOW_W 520
#define WINDOW_H 640
#define WINDOW_MENU_H 128
#define F_WIDTH 200
#define F_HEIGHT 200
#define F_MENU_HEIGHT 50
/////
// Menu row
#define MENU_B_TOP -105
#define MENU_B_BOTTOM -125
/////
// Menu columns
#define MENU_B0_L -90
#define MENU_B0_R -70
#define MENU_B1_L -65
#define MENU_B1_R -45
#define MENU_B2_L -40
#define MENU_B2_R -20
#define MENU_B3_L -15
#define MENU_B3_R 5
#define MENU_B4_L 10
#define MENU_B4_R 30
#define MENU_B5_L 45
#define MENU_B5_R 65
#define MENU_B6_L 70
#define MENU_B6_R 90
//
#define UNIT_SPAWN_DIST 15

#define STARTING_RESOURCES 1000

#define NUMMENUTEXTURES 16

enum MouseMode {NORMAL, BUILD_SUPPLY, BUILD_TOWER};

struct mouseProperties {
	float anchorX, anchorY;
	float xPos, yPos;
	int buttonPressed;
	MouseMode mode;
	bool selecting;
	int UIButton;
	bool aggressionOn;
	bool exploreOn;
} mouseStatus;

struct texture_T {
	GLuint textName;
	int width; // width of image
	int height; // height of image
	int size; // Total number of RGB color component entries (3 x width x height)
	GLubyte *data;
};

world * field = new world;
time_t startT,endT;
vertex p_citadel_pos, c_citadel_pos;
texture_T menuTextures[NUMMENUTEXTURES];
texture_T structTextures[6];
texture_T bannerTextures[2];
texture_T dashboard;
int winState = 0;

//Destroy Log
FILE * outputFile;

void drawDisk(vertex pos, float r) {
	int i;
	float x = pos.x, y = pos.y;

	glBegin(GL_TRIANGLE_FAN);
	glVertex2f(x, y);
	for (i = 0; i <= 360; i+=5) {
		glVertex2f(x + degsin(i) * r, y + degcos(i) * r);
	}
	glEnd();
}

GLuint loadTexture(string fileName, texture_T * textRef) {
	int i;
	int r;
	char testStr[100];
	int testInt;
	FILE * iFile;

	// Attempt opening of file
	if ((iFile = fopen(fileName.c_str(), "r")) == 0) {
		cout << "Failed to open texture file: " << fileName << endl;
		return 0;
	}
	// Check 'P#' designation in .ppm formating
	fscanf(iFile, "%[^\n]\n", testStr);
	if ( strcmp(testStr, "P3") != 0) {
		cout << "Texture file content not P3" << endl;
		return 0;
	}
	fscanf(iFile, "%*[^\n]\n");
	// Acquire image width and height in pixels
	fscanf(iFile, "%d %d\n", &textRef->width, &textRef->height);
	fscanf(iFile, "%d\n", &testInt);
	// Check color component range
	if (testInt != 255) {
		cout << "Color component range is not 255" << endl;
		return 0;                  
	}
	// Determine image size
	textRef->size = textRef->width*textRef->height*3;
			
	// Allocate space for image data
	textRef->data = (GLubyte *)malloc(textRef->size * sizeof(GLubyte));
				
	// Feed image data into texture buffer
	for (i = 0; i < textRef->size; i++) {
		fscanf(iFile, "%d\n", &r);
		textRef->data[i] = (GLubyte) r;
	}
				
	return 1;
}

void textureParameterSet(texture_T * textRef) {
	// allocate a texture names
	glGenTextures( 1, &textRef->textName );

	// select current texture
    glBindTexture( GL_TEXTURE_2D, textRef->textName );

	// select modulate to mix texture with color for shading
	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

	// when texture area is small, bilinear filter the closest mipmap
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
					 GL_LINEAR_MIPMAP_LINEAR );
	// when texture area is large, bilinear filter the original
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

	// the texture wraps over at the edges (repeat)
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );

	 // build texture mipmaps
	gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, textRef->width, textRef->height, GL_RGB, GL_UNSIGNED_BYTE, textRef->data );

	free(textRef->data);
}


void init(void) {
	
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
	glMatrixMode (GL_PROJECTION);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable( GL_BLEND );
	glDisable(GL_DEPTH_TEST);  
	glutInitWindowSize(WINDOW_W, WINDOW_H);
	glutInitWindowPosition(300, 0);
	glutCreateWindow("Project");
	//gluOrtho2D(-100, 100, -100, 100);
	gluOrtho2D(-F_WIDTH/2, F_WIDTH/2, -(F_HEIGHT/2 + F_MENU_HEIGHT), F_HEIGHT/2);

	mouseStatus.xPos = 0;
	mouseStatus.yPos = 0;
	mouseStatus.buttonPressed = -1;
	mouseStatus.mode = NORMAL;
	mouseStatus.selecting = false;
	mouseStatus.UIButton = -1;
	mouseStatus.aggressionOn = true;
	mouseStatus.exploreOn = false;

	field->player_resources = STARTING_RESOURCES;

	//////////////////////////////////texture setup
	int flag = 0;
	glEnable(GL_TEXTURE_2D);
	flag+= loadTexture("triButton.ppm",&menuTextures[0]);
	flag+= loadTexture("triButton_d.ppm",&menuTextures[1]);
	flag+= loadTexture("circButton.ppm",&menuTextures[2]);
	flag+= loadTexture("circButton_d.ppm",&menuTextures[3]);
	flag+= loadTexture("rectButton.ppm",&menuTextures[4]);
	flag+= loadTexture("rectButton_d.ppm",&menuTextures[5]);
	flag+= loadTexture("supButton.ppm",&menuTextures[6]);
	flag+= loadTexture("supButton_d.ppm",&menuTextures[7]);
	flag+= loadTexture("towButton.ppm",&menuTextures[8]);
	flag+= loadTexture("towButton_d.ppm",&menuTextures[9]);
	flag+= loadTexture("pasButton.ppm",&menuTextures[10]);
	flag+= loadTexture("pasButton_d.ppm",&menuTextures[11]);
	flag+= loadTexture("aggButton.ppm",&menuTextures[12]);
	flag+= loadTexture("aggButton_d.ppm",&menuTextures[13]);
	flag+= loadTexture("expButton.ppm",&menuTextures[14]);
	flag+= loadTexture("expButton_d.ppm",&menuTextures[15]);

	flag+= loadTexture("dashboard.ppm",&dashboard);

	flag+= loadTexture("blueCenter.ppm",&structTextures[0]);
	flag+= loadTexture("redCenter.ppm",&structTextures[1]);
	flag+= loadTexture("blueSupply.ppm",&structTextures[2]);
	flag+= loadTexture("redSupply.ppm",&structTextures[3]);
	flag+= loadTexture("blueTower.ppm",&structTextures[4]);
	flag+= loadTexture("redTower.ppm",&structTextures[5]);

	flag+= loadTexture("winBanner.ppm",&bannerTextures[0]);
	flag+= loadTexture("loseBanner.ppm",&bannerTextures[1]);

	if (flag < NUMMENUTEXTURES+9) {
		cout << "At least one texture file could not be loaded" << endl;
	}

	int i;
	for (i = 0; i < NUMMENUTEXTURES; i++)
		textureParameterSet(&menuTextures[i]);
	textureParameterSet(&bannerTextures[0]);
	textureParameterSet(&bannerTextures[1]);
	textureParameterSet(&structTextures[0]);
	textureParameterSet(&structTextures[1]);
	textureParameterSet(&structTextures[2]);
	textureParameterSet(&structTextures[3]);
	textureParameterSet(&structTextures[4]);
	textureParameterSet(&structTextures[5]);
	textureParameterSet(&dashboard);

	//glBindTexture( GL_TEXTURE_2D, 0);

}

void display(void){

	//Clear color buffer
	glClear(GL_COLOR_BUFFER_BIT);

	// Have texturing disabled until textured polygons are encountered
	glDisable(GL_TEXTURE_2D);

	int i, j;
	int agentCount;
	int squadCount = field->squadList.size();
	int structureCount = field->structureList.size();
	float angleMod;
	AVector tempVector;
	vertex tempVertex;
	agent * tempAgent;
	squad * tempSquad;
	triangleAgent * tempTriangle;
	circleAgent * tempCircle;
	rectangleAgent * tempRectangle;
	vertex tempPosition;
	structure * tempStructure;

	// Field color
	/*glColor3f(0.5, 0.5, 0.5);
	glBegin(GL_QUADS);
		glVertex2f(-100, -100); 
		glVertex2f(100, -100);
		glVertex2f(100, 100);
		glVertex2f(-100, 100);
	glEnd();*/

	// Draw Terrain
	field->map.Draw();

	glEnable(GL_TEXTURE_2D);
	glBindTexture( GL_TEXTURE_2D, dashboard.textName );
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_QUADS);
	glTexCoord2d(0.0,0.0); 
	glVertex2f(-100, -100); 
	glTexCoord2d(1.0,0.0); 
	glVertex2f(100, -100);
	glTexCoord2d(1.0,1.0); 
	glVertex2f(100, -150);
	glTexCoord2d(0.0,1.0); 
	glVertex2f(-100, -150);
	glEnd();
	glDisable(GL_TEXTURE_2D);

	/////
	// TEST A* DOTS
	int k;
	int testCount = field->squadList.size();
	for (k=0; k < testCount; k++) {
		list<vertex> test = field->squadList[k]->goalList;
		glColor3f(1.0, 1.0, 1.0);
		vertex testV;
		while (!test.empty()) {
			testV = test.front();
			test.pop_front();
			drawDisk(testV, 2);
		}
	}

	/////
	// Draw Menu
		glEnable(GL_TEXTURE_2D);
		// Button 0
		if (mouseStatus.UIButton != 0)
			glBindTexture( GL_TEXTURE_2D, menuTextures[0].textName );
		else
			glBindTexture( GL_TEXTURE_2D, menuTextures[1].textName );
		glBegin(GL_QUADS);
		glColor3f(0.5, 0.5, 0.5);
		glTexCoord2d(0.0,0.0); glVertex2f(MENU_B0_L, MENU_B_TOP); 
		glTexCoord2d(1.0,0.0); glVertex2f(MENU_B0_R, MENU_B_TOP);
		glTexCoord2d(1.0,1.0); glVertex2f(MENU_B0_R, MENU_B_BOTTOM);
		glTexCoord2d(0.0,1.0); glVertex2f(MENU_B0_L, MENU_B_BOTTOM);
		glEnd();

		// Button 1
		if (mouseStatus.UIButton != 1)
			glBindTexture( GL_TEXTURE_2D, menuTextures[2].textName );
		else
			glBindTexture( GL_TEXTURE_2D, menuTextures[3].textName );
		glBegin(GL_QUADS);
		glColor3f(0.5, 0.5, 0.5);
		glTexCoord2d(0.0,0.0); glVertex2f(MENU_B1_L, MENU_B_TOP); 
		glTexCoord2d(1.0,0.0); glVertex2f(MENU_B1_R, MENU_B_TOP);
		glTexCoord2d(1.0,1.0); glVertex2f(MENU_B1_R, MENU_B_BOTTOM);
		glTexCoord2d(0.0,1.0); glVertex2f(MENU_B1_L, MENU_B_BOTTOM);
		glEnd();

		// Button 2
		if (mouseStatus.UIButton != 2)
			glBindTexture( GL_TEXTURE_2D, menuTextures[4].textName );
		else
			glBindTexture( GL_TEXTURE_2D, menuTextures[5].textName );
		glBegin(GL_QUADS);
		glColor3f(0.5, 0.5, 0.5);
		glTexCoord2d(0.0,0.0); glVertex2f(MENU_B2_L, MENU_B_TOP); 
		glTexCoord2d(1.0,0.0); glVertex2f(MENU_B2_R, MENU_B_TOP);
		glTexCoord2d(1.0,1.0); glVertex2f(MENU_B2_R, MENU_B_BOTTOM);
		glTexCoord2d(0.0,1.0); glVertex2f(MENU_B2_L, MENU_B_BOTTOM);
		glEnd();

		// Button 3
		if (mouseStatus.UIButton != 3)
			glBindTexture( GL_TEXTURE_2D, menuTextures[6].textName );
		else
			glBindTexture( GL_TEXTURE_2D, menuTextures[7].textName );
		glBegin(GL_QUADS);
		glColor3f(0.5, 0.5, 0.5);
		glTexCoord2d(0.0,0.0); glVertex2f(MENU_B3_L, MENU_B_TOP); 
		glTexCoord2d(1.0,0.0); glVertex2f(MENU_B3_R, MENU_B_TOP);
		glTexCoord2d(1.0,1.0); glVertex2f(MENU_B3_R, MENU_B_BOTTOM);
		glTexCoord2d(0.0,1.0); glVertex2f(MENU_B3_L, MENU_B_BOTTOM);
		glEnd();

		// Button 4
		if (mouseStatus.UIButton != 4)
			glBindTexture( GL_TEXTURE_2D, menuTextures[8].textName );
		else
			glBindTexture( GL_TEXTURE_2D, menuTextures[9].textName );
		glBegin(GL_QUADS);
		glColor3f(0.5, 0.5, 0.5);
		glTexCoord2d(0.0,0.0); glVertex2f(MENU_B4_L, MENU_B_TOP); 
		glTexCoord2d(1.0,0.0); glVertex2f(MENU_B4_R, MENU_B_TOP);
		glTexCoord2d(1.0,1.0); glVertex2f(MENU_B4_R, MENU_B_BOTTOM);
		glTexCoord2d(0.0,1.0); glVertex2f(MENU_B4_L, MENU_B_BOTTOM);
		glEnd();

		// Button 5
		if (mouseStatus.aggressionOn)
			glBindTexture( GL_TEXTURE_2D, menuTextures[12].textName );
		else
			glBindTexture( GL_TEXTURE_2D, menuTextures[11].textName );
		glBegin(GL_QUADS);
		glColor3f(0.5, 0.5, 0.5);
		glTexCoord2d(0.0,0.0); glVertex2f(MENU_B5_L, MENU_B_TOP); 
		glTexCoord2d(1.0,0.0); glVertex2f(MENU_B5_R, MENU_B_TOP);
		glTexCoord2d(1.0,1.0); glVertex2f(MENU_B5_R, MENU_B_BOTTOM);
		glTexCoord2d(0.0,1.0); glVertex2f(MENU_B5_L, MENU_B_BOTTOM);
		glEnd();

		// Button 5
		if (mouseStatus.exploreOn)
			glBindTexture( GL_TEXTURE_2D, menuTextures[15].textName );
		else
			glBindTexture( GL_TEXTURE_2D, menuTextures[14].textName );
		glBegin(GL_QUADS);
		glColor3f(0.5, 0.5, 0.5);
		glTexCoord2d(0.0,0.0); glVertex2f(MENU_B6_L, MENU_B_TOP); 
		glTexCoord2d(1.0,0.0); glVertex2f(MENU_B6_R, MENU_B_TOP);
		glTexCoord2d(1.0,1.0); glVertex2f(MENU_B6_R, MENU_B_BOTTOM);
		glTexCoord2d(0.0,1.0); glVertex2f(MENU_B6_L, MENU_B_BOTTOM);
		glEnd();
		glDisable(GL_TEXTURE_2D);
		// Resource Box
		/*
		glColor3f(0.5, 0.5, 0.5);
		glVertex2f(-80, -135); 
		glVertex2f(-60, -135);
		glVertex2f(-60, -145);
		glVertex2f(-80, -145);
		*/
	glEnd();

	/////
	// Draw structures
	for (i=0; i < structureCount; i++) {

		tempStructure = field->structureList[i];
		
		float left = tempStructure->position.x-tempStructure->radius;
		float right = tempStructure->position.x+tempStructure->radius;
		float top = tempStructure->position.y-tempStructure->radius;
		float bottom = tempStructure->position.y+tempStructure->radius;
		
		glEnable(GL_TEXTURE_2D);
		if (BLUE == tempStructure->team)
		{
			glColor3f(0.2, 0.4, 1.0);
			switch (tempStructure->type) {
			case structure::CITADEL:
				glBindTexture( GL_TEXTURE_2D, structTextures[0].textName );
				break;
			case structure::SUPPLY:
				glBindTexture( GL_TEXTURE_2D, structTextures[2].textName );
				break;
			case structure::TOWER:
				glBindTexture( GL_TEXTURE_2D, structTextures[4].textName );
				break;
			}
		}
		else
		{
			glColor3f(0.8, 0, 0);
			switch (tempStructure->type) {
			case structure::CITADEL:
				glBindTexture( GL_TEXTURE_2D, structTextures[1].textName );
				break;
			case structure::SUPPLY:
				glBindTexture( GL_TEXTURE_2D, structTextures[3].textName );
				break;
			case structure::TOWER:
				glBindTexture( GL_TEXTURE_2D, structTextures[5].textName );
				break;
			}
		}
		glBegin(GL_QUADS);
		glTexCoord2d(0.0,0.0); glVertex2f(left, bottom); 
		glTexCoord2d(1.0,0.0); glVertex2f(right, bottom);
		glTexCoord2d(1.0,1.0); glVertex2f(right, top);
		glTexCoord2d(0.0,1.0); glVertex2f(left, top);
		glEnd();
		glDisable(GL_TEXTURE_2D);

		
		//drawDisk(tempStructure->position, tempStructure->radius);

		// Attack laser for towers
		if (NULL != tempStructure->target && tempStructure->atkTimer < TOWER_ATK_DURATION) {
			vertex targetPos;
			if (tempStructure->targetingAgent) {
				targetPos = ((agent*)tempStructure->target)->position;
			} else {
				targetPos = ((structure*)tempStructure->target)->position;
			}

			glBegin(GL_LINES);
			glVertex2f(targetPos.x, targetPos.y);
			glVertex2f(tempStructure->position.x, tempStructure->position.y);
			glEnd();
		}
	}

	// Draw resources
	for (vector<resource>::iterator it = field->resourceList.begin(); it != field->resourceList.end(); it++)
	{
		it->Draw();
	}

	// Draw agents from each squad
	// (different draw method depending on agent type)
	for (i = 0; i < squadCount; i++) {
		
		// Consider one squad
		tempSquad = field->squadList[i];
		agentCount = tempSquad->agentList.size();

		// For each agent in squad...
		for (j=0; j < agentCount; j++) {
			tempAgent = tempSquad->agentList[j];
			tempPosition = tempAgent->position;


			// attack laser

			if (tempSquad->team == RED)
				glColor3f(1.0, 0.0, 0.0);
			else 
				glColor3f(0.0, 0.0, 1.0);
			if(tempAgent->target.targetObj != 0 &&
				tempAgent->atkTimer < 1000) {
					glBegin(GL_LINES);
					vertex tempVert = tempAgent->getTargetPosition();
					glVertex2f(tempVert.x, tempVert.y);
					glVertex2f(tempAgent->position.x, tempAgent->position.y);
					glEnd();
			}

			// Determine the agent type
			switch (tempAgent->type) {

				// DRAWING TRIANGLE AGENTS
				case TRIANGLE:
					if (tempSquad->selected)
						glColor3f(0.0, 1.0, 1.0);
					else if (tempSquad->team == RED)
						glColor3f(1.0, 0.0, 0.0);
					else 
						glColor3f(0.0, 0.0, 1.0);
					glBegin(GL_TRIANGLES);

					// Cast generic agent into triangle agent 
					tempTriangle = (triangleAgent *) tempAgent;

					// 1st triangle vertex
					if (tempTriangle->velocity.length() == 0)
						tempVector = AVector(0,1);
					else 
						tempVector = tempTriangle->velocity.normalize() * (tempTriangle->centerLength / 2);
					tempVertex = tempPosition + tempVector;
					glVertex2f(tempVertex.x, tempVertex.y);
		
					// 2nd triangle vertex
					angleMod = 180 - tempTriangle->angleRef;
					tempVector = AVector(degsin(tempTriangle->direction + angleMod),degcos(tempTriangle->direction + angleMod)); //should be normalized unit vector
					tempVector = tempVector * tempTriangle->sideLength;
					glVertex2f(tempVector.x+tempVertex.x, tempVector.y+tempVertex.y);

					angleMod = 180 + tempTriangle->angleRef;
					tempVector = AVector(degsin(tempTriangle->direction + angleMod),degcos(tempTriangle->direction + angleMod)); //should be normalized unit vector
					tempVector = tempVector * tempTriangle->sideLength;
					glVertex2f(tempVector.x+tempVertex.x, tempVector.y+tempVertex.y);

					glEnd();
					break;

				// DRAWING CIRCLE AGENTS
				case CIRCLE:
					if (tempSquad->selected)
						glColor3f(0.0, 1.0, 1.0);
					else if (tempSquad->team == RED)
						glColor3f(1.0, 0.0, 0.0);
					else 
						glColor3f(0.0, 0.0, 1.0);
					
					// Cast generic agent into triangle agent 
					tempCircle = (circleAgent *) tempAgent;

					drawDisk(tempCircle->position, tempCircle->radius);

					break;

				// DRAWING RECTANGLE AGENTS
				case RECTANGLE:
					if (tempSquad->selected)
						glColor3f(0.0, 1.0, 1.0);
					else if (tempSquad->team == RED)
						glColor3f(1.0, 0.0, 0.0);
					else 
						glColor3f(0.0, 0.0, 1.0);
					glBegin(GL_QUADS);

					// Cast generic agent into triangle agent 
					tempRectangle = (rectangleAgent *) tempAgent;

					// Vector to top-right corner					
					AVector v = AVector(tempRectangle->width, tempRectangle->length) / 2;
					vertex p = tempRectangle->position;

					//float theta = degacos(tempRectangle->velocity.normalize().dot(AVector(0,1)));
					//float theta = -tempRectangle->velocity.getDirection();
					float theta = -tempRectangle->direction;

					// Calculate the corners
					glVertex2f(p.x + v.x*degcos(theta) - v.y*degsin(theta),
							   p.y + v.y*degcos(theta) + v.x*degsin(theta));

					glVertex2f(p.x + v.x*degcos(theta) + v.y*degsin(theta),
							   p.y - v.y*degcos(theta) + v.x*degsin(theta));

					glVertex2f(p.x - v.x*degcos(theta) + v.y*degsin(theta),
							   p.y - v.y*degcos(theta) - v.x*degsin(theta));

					glVertex2f(p.x - v.x*degcos(theta) - v.y*degsin(theta),
							   p.y + v.y*degcos(theta) - v.x*degsin(theta));
					
					glEnd();
					break;
			}

		}

	}

	// Selection box
	if (mouseStatus.buttonPressed == GLUT_LEFT_BUTTON) {
		glColor4f(1.0, 0.0, 0.0, 0.3);
		glBegin(GL_LINE_STRIP);
		glVertex2f(mouseStatus.anchorX, mouseStatus.anchorY);
		glVertex2f(mouseStatus.anchorX, mouseStatus.yPos);
		glVertex2f(mouseStatus.xPos, mouseStatus.yPos);
		glVertex2f(mouseStatus.xPos, mouseStatus.anchorY);

		//WHEN USING LINE STRIP:
		glVertex2f(mouseStatus.anchorX, mouseStatus.anchorY);

		glEnd();
	}

	// Draw Text
	// =========
	glColor3f(0.0, 0.6, 0.2);

	// Resources
	// ---------
	char buffer[50];
	int n = sprintf_s(buffer, "$%d", field->player_resources);
	glRasterPos2d(-80, -145);
	for(int i = 0; i < n; i++)
	{
		glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, buffer[i]);
	}

	// Population count
	// ---------
	
	n = sprintf_s(buffer, "%d/%d", field->bluePopulation,field->blueSupplies); // TODO

	glRasterPos2d(0, -145);
	for(int i = 0; i < n; i++)
	{
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, buffer[i]);
	}
	

	// Unit/Structure costs
	// --------------------
	// Triangles
	n = sprintf_s(buffer, "$%d", SQ_TRI_COST);
	glRasterPos2d(MENU_B0_L+2, MENU_B_BOTTOM-6);
	for(int i = 0; i < n; i++)
	{
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, buffer[i]);
	}

	// Circles
	n = sprintf_s(buffer, "$%d", SQ_CIR_COST);
	glRasterPos2d(MENU_B1_L+2, MENU_B_BOTTOM-6);
	for(int i = 0; i < n; i++)
	{
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, buffer[i]);
	}

	// Rectangles
	n = sprintf_s(buffer, "$%d", SQ_REC_COST);
	glRasterPos2d(MENU_B2_L+2, MENU_B_BOTTOM-6);
	for(int i = 0; i < n; i++)
	{
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, buffer[i]);
	}

	// Supply Depots
	n = sprintf_s(buffer, "$%d", COST_SUPPLY);
	glRasterPos2d(MENU_B3_L+2, MENU_B_BOTTOM-6);
	for(int i = 0; i < n; i++)
	{
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, buffer[i]);
	}

	// Towers
	n = sprintf_s(buffer, "$%d", COST_TOWER);
	glRasterPos2d(MENU_B4_L+2, MENU_B_BOTTOM-6);
	for(int i = 0; i < n; i++)
	{
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, buffer[i]);
	}

	//==========

	// ENDGAME BANNER
	if (winState != 0) {
		glEnable(GL_TEXTURE_2D);
		if (winState == 1)
			glBindTexture( GL_TEXTURE_2D, bannerTextures[0].textName);
		else
			glBindTexture( GL_TEXTURE_2D, bannerTextures[1].textName);
		glBegin(GL_QUADS);
		// Button 0
		glColor3f(0.5, 0.5, 0.5);
		glTexCoord2d(0.0,0.0); glVertex2f(-90, 20); 
		glTexCoord2d(1.0,0.0); glVertex2f(90, 20);
		glTexCoord2d(1.0,1.0); glVertex2f(90, -20);
		glTexCoord2d(0.0,1.0); glVertex2f(-90, -20);
		glEnd();
	}

	glutSwapBuffers();
}

void planTower(structure *tower, float dt)
{
	// if the tower's target is dead, clear it
	if (NULL != tower->target)
	{
		if (tower->targetingAgent)
		{
			if (((agent*)tower->target)->hp <= 0)
			{
				tower->target = NULL;
				tower->targetingAgent = false;
			}
		}
		else
		{
			if (((structure*)tower->target)->hp <= 0)
			{
				tower->target = NULL;
				tower->targetingAgent = false;
			}
		}
	}

	// Update attack timer
	tower->atkTimer += dt;

	if (TOWER_ATK_DELAY <= tower->atkTimer)
	{
		tower->atkTimer = TOWER_ATK_DELAY;
	}
	else
	{
		// Nothing else to do here
		return;
	}

	// check if the tower has a valid agent target
	if (NULL == tower->target 
		|| !tower->targetingAgent 
		|| ((agent*)tower->target)->position.distance(tower->position) > TOWER_ATK_RADIUS)
	{
		tower->target = NULL;
		// Tower needs to search for an agent target
		for (int i= 0; i < field->squadList.size(); i++)
		{
			if (tower->team != field->squadList[i]->team)
			{  // Check enemy squad for targets
				for (int j = 0; j < field->squadList[i]->agentList.size(); j++)
				{
					agent *a = field->squadList[i]->agentList[j];
					if (a->position.distance(tower->position) < TOWER_ATK_RADIUS)
					{
						// Target found!
						tower->target = a;
						tower->targetingAgent = true;
						break;
					}
				}
			}
			if (NULL != tower->target)
			{ // target was found
				break;
			}
		}
	}

	// Check for structures to target if no agent is found
	if (NULL == tower->target)
	{
		// Search structures
		for (int i = 0; i < field->structureList.size(); i++)
		{
			structure *s = field->structureList[i];
			if (s->team != tower->team && s->position.distance(tower->position) <= TOWER_ATK_RADIUS + s->radius)
			{
				// Enemy structure is in range
				tower->target = s;
				tower->targetingAgent = false;
				break;
			}
		}
	}

	// Finally, execute attack
	if (NULL != tower->target)
	{
		// Update attack timer
		tower->atkTimer -= TOWER_ATK_DELAY;
		
		// Deal damage
		if (tower->targetingAgent)
		{
			((agent*)tower->target)->hp -= TOWER_ATK_DAMAGE;
			if (((agent*)tower->target)->hp <= 0)
			{
				field->destroyList.push_back(tower->target);
			}
		}
		else
		{
			((structure*)tower->target)->hp -= TOWER_ATK_DAMAGE;
			if (((structure*)tower->target)->hp <= 0)
			{
				field->destroyList.push_back(tower->target);
			}
		}
	}
	
}

#define AI_SPAWN_DELAY 12000
#define AI_MAX_SPAWN 3
float AI_timer = 0;
void EnemyAI(float dt)
{
	AI_timer += dt*randRange(0, 1.25);
	if (AI_timer < AI_SPAWN_DELAY) {
		return;
	}

	// AI can spawn units
	AI_timer -= AI_SPAWN_DELAY;

	// Give the player some money
	field->player_resources += 200;
	if (RESOURCE_PLAYER_MAX < field->player_resources)
	{
		field->player_resources = RESOURCE_PLAYER_MAX;
	}

	AVector v = (vertex(0,0) - c_citadel_pos).normalize();
	squad *newSquad;
	bool failure = false;
	int i = 0;
	while(field->redPopulation < field->redSupplies && !failure && i < AI_MAX_SPAWN)
	{
		i++;
		int diff = field->redSupplies - field->redPopulation;
		int result;
		switch((int)floor(randRange(1, 3.99)))
		{
			case 1:
				newSquad = new squad(RED, RECTANGLE, c_citadel_pos + v*UNIT_SPAWN_DIST);
				result = field->addSquad(newSquad);

				if (0 == result){
					newSquad->activateExplore(&field->map);
					newSquad->aggressive = true;
					break;
				} else {
					delete newSquad;
				}
			case 2:
				newSquad = new squad(RED, CIRCLE, c_citadel_pos + v*UNIT_SPAWN_DIST);
				result = field->addSquad(newSquad);

				if (0 == result){
					newSquad->activateExplore(&field->map);
					newSquad->aggressive = true;
					break;
				} else {
					delete newSquad;
				}
			case 3:
				newSquad = new squad(RED, TRIANGLE, c_citadel_pos + v*UNIT_SPAWN_DIST);
				result = field->addSquad(newSquad);

				if (0 == result){
					newSquad->activateExplore(&field->map);
					newSquad->aggressive = true;
					break;
				} else {
					delete newSquad;
				}
			default:
				failure = true;
				break;
		}
	}
}

void Planning(void) {
	 
	if (0 != winState)
	{
		return;
	}

	int i;
	//AVector sepVector, cohVector, alignVector, borderVector, obstacleVector, goalVector;
	int squadCount = field->squadList.size();
	//agent * tempAgent;

	// Hit the stopwatch and calc the time difference
	time_t diffT;
	endT = clock();
	diffT = endT-startT;

	// Spawn resources
	field->spawnResources((float)diffT);

	// Execute Red team's master plan
	EnemyAI(diffT);

	// For each squad...
	for (i = 0; i < squadCount; i++) {

		field->updateSquadAgents(i, diffT, outputFile);

	}

	// Do tower planning/attacks
	for (i = 0; i < field->structureList.size(); i++)
	{
		if (structure::TOWER == field->structureList[i]->type)
		{
			planTower(field->structureList[i], diffT);
		}
	}

	// Do agent/structure cleanup if something was destroyed
	if (!field->destroyList.empty()) {
		winState = field->destroyCleanup(outputFile);
	}

	startT = endT;

	glutPostRedisplay();

}

void noResize(int width, int height) {
	glutReshapeWindow(WINDOW_W, WINDOW_H); 
}

bool placeStructure(structure::TYPE t, vertex p, team_T team)
{
	if (field->structureList.size() + 1 >= field->structureMax)
	{ // Too many structures to be able to place
		return false;
	}

	structure *s = new structure(t, vertex(0,0), team);

	// If structure is a supply depot, update the population maximum
	bool supplyFlag = true;
	if (s->type == structure::SUPPLY) {
		if (s->team == BLUE) {
			if (!(field->blueSupplies+SUPPLYAMMOUNT > POP_HARDCAP))
				field->blueSupplies += SUPPLYAMMOUNT;
			else
				supplyFlag = false;
		}
		else {
			if (!(field->redSupplies+SUPPLYAMMOUNT > POP_HARDCAP))
				field->redSupplies += SUPPLYAMMOUNT;
			else
				supplyFlag = false;
		}
	}

	if (supplyFlag) {
		bool result = s->occupy(&(field->map), p);
	
		if (!result)
		{ // Occupation failed
			delete s;
			return false;
		}

	
		field->addStructure(s);
	}
	else {
		delete s;
		return false;
	}

	return true;
}

/*
void mouseGoal(int mX, int mY) {
	float x = mX, y = mY;
	float xmap = (x/WINDOW_W)*F_WIDTH-(F_WIDTH/2); 
	float ymap = -((y/WINDOW_H)*F_HEIGHT-(F_HEIGHT/2));

	field->goal = vertex(xmap, ymap);
	//field->goalActive = true;
}
*/

int getClickedButton(int x, int y)
{
	if (MENU_B_BOTTOM <= y && y <= MENU_B_TOP)
	{
		if (MENU_B0_L < x && x < MENU_B0_R)
			return 0;
		else if (MENU_B1_L < x && x < MENU_B1_R)
			return 1;
		else if (MENU_B2_L < x && x < MENU_B2_R)
			return 2;
		else if (MENU_B3_L < x && x < MENU_B3_R)
			return 3;
		else if (MENU_B4_L < x && x < MENU_B4_R)
			return 4;
		else if (MENU_B5_L < x && x < MENU_B5_R)
			return 5;
		else if (MENU_B6_L < x && x < MENU_B6_R)
			return 6;
		else
			return -1;
	}
	return -1;
}

float mouseMapX(float mx) {
	return ((mx)/WINDOW_W)*F_WIDTH-(F_WIDTH/2.0);
}

float mouseMapY(float my) {
	return -(((my)/(WINDOW_H-WINDOW_MENU_H))*F_HEIGHT-(F_HEIGHT/2.0));
}

void activeMotion(int mX, int mY) {
	float x = mX, y = mY;
	float xmap = mouseMapX(x);
	float ymap = mouseMapY(y);

	if (mouseStatus.buttonPressed == GLUT_LEFT_BUTTON) {
		mouseStatus.xPos = xmap;
		mouseStatus.yPos = ymap;
		glutPostRedisplay();
	}
}

void click (int button, int state, int mX, int mY) {
	int i;

	float x = mX, y = mY;
	float xmap = mouseMapX(x);
	float ymap = mouseMapY(y);

	squad * currentSquad;
	int numSquads = field->squadList.size();

	// Note: Map interaction only happens when the mouse button is lifted.
	//       When the mouse button is pressed background calculations are 
	//       performed until the button is liften to determine action


	if (button == GLUT_LEFT_BUTTON){
		// Note the position of the mouse when clicked
		if (state == GLUT_DOWN) {
			
			if(ymap < -(F_HEIGHT/2)) { 
				// User clicked in the menu area
				mouseStatus.mode = NORMAL;
				squad * newSquad;       //used in case 1
				vector<squad*> subList; //used in case 6 (had to declare it here, for some reason)
				int exploreCount = 0;   //used in case 6 (had to declare it here, for some reason)
				int aggressionCount = 0;   //used in case 6 (had to declare it here, for some reason)
				switch (getClickedButton(xmap, ymap)) {
					case 0:
						mouseStatus.UIButton = 0;
						// TODO: Spawn triangles at the citadel
						if (SQ_TRI_COST <= field->player_resources)
						{

							AVector v = (vertex(0,0) - p_citadel_pos).normalize();

							newSquad = new squad(BLUE,TRIANGLE, p_citadel_pos + v*UNIT_SPAWN_DIST);
							int result = field->addSquad(newSquad);

							if (0 == result)
							{
								field->player_resources -= SQ_TRI_COST;
							}
							else delete newSquad;
						}
						break;
					case 1:
						mouseStatus.UIButton = 1;
						// TODO: Spawn circles at the citadel
						if (SQ_CIR_COST <= field->player_resources)
						{
							AVector v = (vertex(0,0) - p_citadel_pos).normalize();

							newSquad = new squad(BLUE,CIRCLE, p_citadel_pos + v*UNIT_SPAWN_DIST);
							int result = field->addSquad(newSquad);

							if (0 == result)
							{
								field->player_resources -= SQ_CIR_COST;
							}
							else delete newSquad;
						}
						break;
					case 2:
						mouseStatus.UIButton = 2;
						// TODO: Spawn rectangles at the citadel
						if (SQ_REC_COST <= field->player_resources)
						{
							AVector v = (vertex(0,0) - p_citadel_pos).normalize();

							newSquad = new squad(BLUE,RECTANGLE, p_citadel_pos + v*UNIT_SPAWN_DIST);
							int result = field->addSquad(newSquad);

							if (0 == result)
							{
								field->player_resources -= SQ_REC_COST;
							}
							else delete newSquad;
						}
						break;
					case 3:
						mouseStatus.UIButton = 3;
						// TODO: Attempt to initiate construction of a supply depot
						mouseStatus.mode = BUILD_SUPPLY;
						break;
					case 4:
						mouseStatus.UIButton = 4;
						// TODO: Attempt to initiate construction of a tower
						mouseStatus.mode = BUILD_TOWER;
						break;
					case 5:
						mouseStatus.UIButton = 5;
						mouseStatus.aggressionOn = !mouseStatus.aggressionOn;
						// TODO: Toggle any selected agents' aggression
						for (int k=0; k < numSquads; k++) {
							currentSquad = field->squadList[k];
							if (currentSquad->selected) {
								currentSquad->aggressive = mouseStatus.aggressionOn;
							}
						}
						break;
					case 6:
						mouseStatus.UIButton = 6;
						mouseStatus.exploreOn = !mouseStatus.exploreOn;
						// Check each squad
						for (int k=0; k < numSquads; k++) {
							currentSquad = field->squadList[k];
							// If squad is selected, add it to reference list
							if (currentSquad->selected) {
								subList.push_back(currentSquad);
								// If selected squad is exploring, take note
								if (currentSquad->isExploring()) 
									exploreCount++;
							}
						}
						// Check if exploring squads outweigh the non-exploring squads, or vice versa
						// If the sublist is mostly exploring, set all to stop exploring
						if (exploreCount >= subList.size()) {
							for (int k=0; k < subList.size(); k++) {
								subList[k]->deactivateExplore();
							}
						}
						// If the submist is mostly not exploring, set all to explore
						else {
							for (int k=0; k < subList.size(); k++) {
								subList[k]->activateExplore(&field->map);
							}
						}
						break;
					default:
						// do nothing
						break;
				}
			} else {
				// User did not click in the menu area
				switch (mouseStatus.mode) {
					case NORMAL:
						mouseStatus.xPos = mouseStatus.anchorX = xmap;
						mouseStatus.yPos = mouseStatus.anchorY = ymap;
						mouseStatus.buttonPressed = GLUT_LEFT_BUTTON;
						mouseStatus.selecting = true;
						break;
					case BUILD_SUPPLY:
						// Check if they have enough resources
						if (COST_SUPPLY <= field->player_resources) {
							if (placeStructure(structure::SUPPLY, vertex(xmap,ymap), BLUE)) {
								field->player_resources -= COST_SUPPLY;
								field->structures_changed = true;
							}
						}
						break;
					case BUILD_TOWER:
						// Check if they have enough resources
						if (COST_TOWER <= field->player_resources) {
							if (placeStructure(structure::TOWER, vertex(xmap,ymap), BLUE)) {
								field->player_resources -= COST_TOWER;
								field->structures_changed = true;
							}
						}
						break;
					default:
						mouseStatus.UIButton = -1;
						break;
				}
				// Set mouse back to normal mode unless the player holds shift
				int modFlags = glutGetModifiers();
				if(modFlags != GLUT_ACTIVE_SHIFT)
				{
					mouseStatus.mode = NORMAL;
				}
			}
					
		}
		// When mouse is lifted, perform action based on status of mouse
		else if (state == GLUT_UP) {

			mouseStatus.UIButton = -1;

			// If the mouse hasn't moved, treat as a normal click (deselect all squads)
			if (mouseStatus.anchorX == xmap && mouseStatus.anchorY == ymap) {
				mouseStatus.aggressionOn = true;
				mouseStatus.exploreOn = false;
				for (i=0; i < numSquads; i++)
					field->squadList[i]->selected = false;
			}
			// If mouse has moved, determine box selection
			else if (mouseStatus.selecting) {

				// Determine box boundaries
				float left, right, bottom, top;
				if (mouseStatus.anchorX < xmap) {
					left = mouseStatus.anchorX;
					right = xmap;
				}
				else {
					left = xmap;
					right = mouseStatus.anchorX;
				}
				if (mouseStatus.anchorY < ymap) {
					bottom = mouseStatus.anchorY;
					top = ymap;
				}
				else {
					bottom = ymap;
					top = mouseStatus.anchorY;
				}

				int selectCount = 0;
				int aggressiveCount = 0;
				int exploreCount = 0;
				for (i=0; i < numSquads; i++) {
					currentSquad = field->squadList[i];

					if (BLUE == currentSquad->team && currentSquad->isBoxSelected(left, right, bottom, top)){
						currentSquad->selected = true;
						selectCount++;
						if (currentSquad->aggressive) aggressiveCount++;
						if (currentSquad->isExploring()) exploreCount++;
					}
					else currentSquad->selected = false;
				}
				mouseStatus.selecting = false;
				
				if (aggressiveCount >= selectCount-aggressiveCount) mouseStatus.aggressionOn = true;
				else mouseStatus.aggressionOn = false;
				if (exploreCount > selectCount-exploreCount) mouseStatus.exploreOn = true;
				else mouseStatus.exploreOn = false;
			}
			mouseStatus.buttonPressed = -1;
		}
	}

	//Right-click functionality (squad objectives)
	else if (button == GLUT_RIGHT_BUTTON){
		if (state == GLUT_DOWN) {
			mouseStatus.buttonPressed = GLUT_RIGHT_BUTTON;
		}
		else if (state == GLUT_UP) {
			int k;
			int modFlags = glutGetModifiers();
			for (k=0; k < numSquads; k++) {
				currentSquad = field->squadList[k];
				if (currentSquad->selected) {
					currentSquad->goalList = field->AStarPlan(currentSquad, vertex(xmap,ymap));
					
					if (GLUT_ACTIVE_SHIFT == modFlags)
					{
						// If the player shift-clicks, issue an attack-move
						currentSquad->aggressive = true;
					}
					else
					{
						// If the player just licks, set to peaceful so they just move
						currentSquad->aggressive = false;
					}
				}
			}
			if (GLUT_ACTIVE_SHIFT == modFlags)mouseStatus.aggressionOn=true;
			else mouseStatus.aggressionOn = false;
			mouseStatus.buttonPressed = -1;
			startT = clock();
		}
	}
}

void keyDown(unsigned char key, int x, int y)
{

}

void keyUp(unsigned char key, int x, int y)
{

}

void keyDownSpecial(int key, int x, int y)
{

}

void keyUpSpecial(int key, int x, int y)
{

}



/*
void worldMenu(int selection) {
	structure * inputStructure;
	field->resetStructures();

	switch (selection) {
	case 0:
		placeStructure(structure::CITADEL, vertex(3, 8));
		placeStructure(structure::PRODUCTION, vertex(43, -68));
		placeStructure(structure::SUPPLY, vertex(-23, -68));
		placeStructure(structure::TOWER, vertex(-50, -50));
		break;
	case 1:
		placeStructure(structure::CITADEL, vertex(-100, -100));
		break;
	case 2:
		
		break;
	}
	startT = clock();
}
*/

/*
void Menu(int selection) {
	switch (selection) {
	case 0:
		if (field->goalActive == true) mode = NORMAL;
		else mode = PLACING;
		break;
	case 1:
		if (mode == NORMAL) {
			field->goalActive = false;
			mode = PLACING;
		}
		else if (mode == PLACING) {
			field->goalActive = true;
			mode = NORMAL;
		}
		break;
	case 2:
		field->resetSquads();
		break;
	}
	startT = clock();
}
*/

int main(int argc, char **argv) {

	outputFile = fopen("destroyLog.txt","w");

	//Initialize glut
	glutInit(&argc,argv);

	//Initialize glut/opengl settings
	init();

	//Define the display callback function
	glutDisplayFunc(display);

	//Define idle callback function
	glutIdleFunc(Planning);

	//Define window resize callback function
	glutReshapeFunc(noResize);

	/*
	//Define passive mouse motion callback
	glutPassiveMotionFunc(mouseGoal);
	*/

	//Define mouse motion callback
	glutMotionFunc(activeMotion);

	//Define mouse click callback function
	glutMouseFunc(click);

	//Define keyboard callback functions
	glutKeyboardFunc(keyDown);
	glutKeyboardUpFunc(keyUp);
	glutSpecialFunc(keyDownSpecial);
	glutSpecialUpFunc(keyUpSpecial);

	/*
	//Define submenu
	int submenu1 = glutCreateMenu(worldMenu);
	glutAddMenuEntry("Scene 1",0);
	glutAddMenuEntry("Scene 2",1);
	glutAddMenuEntry("Scene 3",2);
	glutAddMenuEntry("Reset",3);
	*/

	/*
	//Define main menu
	glutCreateMenu(Menu);
	glutAddMenuEntry("GO!",0);
	glutAddMenuEntry("Toggle Agents Placement",1);
	glutAddMenuEntry("Reset Agents",2);
	glutAddSubMenu("Switch Scene",submenu1);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	*/

	// Create Terrain
	//field->map.Load_Test_Map_3();

	////////////////////////TEST SETUP
	
	////squad * testSquad = new squad(RED, TRIANGLE, vertex(90,-90));
	//
	////field->addSquad(testSquad);
	//
	//squad * testSquad = new squad(BLUE, TRIANGLE, vertex(-90,90));
	//field->addSquad(testSquad);
	////testSquad = new squad(BLUE, TRIANGLE, vertex(-80,80));
	////field->addSquad(testSquad);
	//
	//
	//testSquad = new squad(RED, CIRCLE, vertex(-90,-90));
	//field->addSquad(testSquad);
	//
	//testSquad = new squad(BLUE, RECTANGLE, vertex(90,90));
	//field->addSquad(testSquad);
	
	//////////////////////////////////
	// Setup citadels and starting units

	float y = randRange(-80, 80);

	p_citadel_pos = vertex(-80, y);
	c_citadel_pos = vertex(80, -y);

	placeStructure(structure::CITADEL, p_citadel_pos, BLUE);
	placeStructure(structure::CITADEL, c_citadel_pos, RED);

	// Setup player's starting units
	squad * newSquad = new squad(BLUE, TRIANGLE, vertex(-70,65));
	field->addSquad(newSquad);
	newSquad = new squad(BLUE, TRIANGLE, vertex(-70,0));
	field->addSquad(newSquad);
	newSquad = new squad(BLUE, TRIANGLE, vertex(-70,-65));
	field->addSquad(newSquad);

	// Setup Red's base
	placeStructure(structure::TOWER, vertex(37.5, -87.5), RED);

	placeStructure(structure::TOWER, vertex(37.5, -72.5), RED);
	placeStructure(structure::SUPPLY, vertex(45,-65), RED);
	placeStructure(structure::SUPPLY, vertex(45,-55), RED);
	placeStructure(structure::SUPPLY, vertex(45,-45), RED);
	placeStructure(structure::SUPPLY, vertex(55,-65), RED);
	placeStructure(structure::SUPPLY, vertex(55,-55), RED);
	placeStructure(structure::SUPPLY, vertex(55,-45), RED);
	placeStructure(structure::TOWER, vertex(37.5, -37.5), RED);
	
	placeStructure(structure::TOWER, vertex(27.5, -17.5), RED);
	placeStructure(structure::SUPPLY, vertex(35, -10), RED);
	placeStructure(structure::SUPPLY, vertex(35,   0), RED);
	placeStructure(structure::SUPPLY, vertex(35,  10), RED);
	placeStructure(structure::SUPPLY, vertex(45, -10), RED);
	placeStructure(structure::SUPPLY, vertex(45,   0), RED);
	placeStructure(structure::SUPPLY, vertex(45,  10), RED);
	placeStructure(structure::TOWER, vertex(27.5, 17.5), RED);
	
	placeStructure(structure::TOWER, vertex(37.5, 37.5), RED);
	placeStructure(structure::SUPPLY, vertex(45, 65), RED);
	placeStructure(structure::SUPPLY, vertex(45, 55), RED);
	placeStructure(structure::SUPPLY, vertex(45, 45), RED);
	placeStructure(structure::SUPPLY, vertex(55, 65), RED);
	placeStructure(structure::SUPPLY, vertex(55, 55), RED);
	placeStructure(structure::SUPPLY, vertex(55, 45), RED);
	placeStructure(structure::TOWER, vertex(37.5, 72.5), RED);
	
	placeStructure(structure::TOWER, vertex(37.5, 87.5), RED);




	//////////////////////////////////

	//int start;
	//cin >> start;

	startT = clock();

	glutMainLoop();

	return 0;
}